#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>

#define N 128

int main(int argc, char const *argv[])
{
    sem_t *sem_w1;
    sem_t *sem_w2;
    sem_t *sem_r1;
    sem_t *sem_r2;


    //创建一个信号量
    sem_w1 = sem_open("sem_w1", O_RDWR | O_CREAT, 0664, 1);
    if (sem_w1 == SEM_FAILED)
    {
        perror("sem_open");
        exit(-1);
    }

    sem_w2 = sem_open("sem_w2", O_RDWR | O_CREAT, 0664, 0);
    if (sem_w2 == SEM_FAILED)
    {
        perror("sem_open");
        exit(-1);
    }

    sem_r1 = sem_open("sem_r1", O_RDWR | O_CREAT, 0664, 0);
    if (sem_r1 == SEM_FAILED)
    {
        perror("sem_open");
        exit(-1);
    }

    sem_r2 = sem_open("sem_r2", O_RDWR | O_CREAT, 0664, 0);
    if (sem_r2 == SEM_FAILED)
    {
        perror("sem_open");
        exit(-1);
    }

    int value;
    sem_getvalue(sem_w1, &value);
    printf("sem_w1=%d\n", value);

    sem_getvalue(sem_w2, &value);
    printf("sem_w2=%d\n", value);

    sem_getvalue(sem_r1, &value);
    printf("sem_r1=%d\n", value);

    sem_getvalue(sem_r2, &value);
    printf("sem_r2=%d\n", value);


    // 1. 生成一个IPC 唯一key值
    key_t key = ftok("/home", 1);
    if (key < 0)
    {
        perror("key");
        exit(-1);
    }
    printf("key=%#x\n", key);
    int shmid = shmget(key, N, IPC_CREAT | 0664); //如果不存在就创建，存在就打开
    if (shmid < 0)
    {
        perror("shmid");
        exit(-1);
    }
    printf("shmid=%d\n", shmid);
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    void *shmaddr = shmat(shmid, NULL, 0); //把共享内存映射到进程内，进程就可以访问这段内存了
    if (shmaddr == (void *)-1)
    {
        perror("shmaddr");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    //memset(shmaddr, 0, N); //对共享内存进行清空

    pid_t pid = fork();
    if (pid < 0)
    {
        perror("pid");
        exit(-1);
    }
    else if (pid == 0)
    {
        while (1)
        {
            sem_wait(sem_r1);
            printf("buf=%s\n",(char *)shmaddr);
            sleep(1);
            sem_post(sem_w2);
        }
    }
    else
    {
        while (1)
        {
            sem_wait(sem_r2);
            printf("buf=%s\n",(char *)shmaddr);
            sleep(1);
            sem_post(sem_w1);
        }
    }

    int ret = shmdt(shmaddr);
    if (ret < 0)
    {
        perror("ret");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    ret = shmctl(shmid, IPC_RMID, NULL);
    if (ret < 0)
    {
        perror("ret");
        exit(-1);
    }
    system("ipcs -m"); //执行linux系统的一个命令 查看系统的共享内存

    return 0;
}
